package org.javahispano.javacup.tacticas_aceptadas.ricardoMQ1984;

import java.awt.Color;
import java.util.LinkedList;
import org.javahispano.javacup.modelo.*;
import java.util.List;
import java.util.Random;

public class La_Isla_FC implements Tactica {

    Posicion alineacion1[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-7.132867132867133,-30.88235294117647),
        new Posicion(7.608391608391608,-31.83257918552036),
        new Posicion(18.06993006993007,-24.468325791855204),
        new Posicion(-19.496503496503497,-24.468325791855204),
        new Posicion(3.5664335664335667,-9.502262443438914),
        new Posicion(6.181818181818182,21.380090497737555),
        new Posicion(-6.181818181818182,22.092760180995477),
        new Posicion(-18.06993006993007,33.02036199095023),
        new Posicion(-5.944055944055944,2.6131221719457014),
        new Posicion(19.020979020979023,31.59502262443439)
    };

    Posicion alineacion2[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-7.608391608391608,-34.20814479638009),
        new Posicion(7.132867132867133,-33.73303167420815),
        new Posicion(18.78321678321678,-30.88235294117647),
        new Posicion(-20.20979020979021,-30.407239819004527),
        new Posicion(9.986013986013985,-18.29185520361991),
        new Posicion(-14.027972027972028,-18.766968325791854),
        new Posicion(17.356643356643357,33.257918552036195),
        new Posicion(-6.895104895104895,0.7126696832579186),
        new Posicion(3.5664335664335667,22.330316742081447),
        new Posicion(-8.321678321678322,30.6447963800905)
    };

    Posicion alineacion3[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-35.78358208955224),
        new Posicion(12.717557251908397,-35.26119402985075),
        new Posicion(28.290076335877863,-28.470149253731343),
        new Posicion(-28.290076335877863,-28.470149253731343),
        new Posicion(14.793893129770993,-18.544776119402986),
        new Posicion(-17.389312977099234,-19.58955223880597),
        new Posicion(-23.618320610687025,-0.7835820895522387),
        new Posicion(5.969465648854961,-5.485074626865671),
        new Posicion(0.2595419847328244,-0.26119402985074625),
        new Posicion(22.580152671755727,-1.3059701492537314)
    };

    Posicion alineacion4[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-35.78358208955224),
        new Posicion(12.717557251908397,-35.26119402985075),
        new Posicion(28.290076335877863,-28.470149253731343),
        new Posicion(-28.290076335877863,-28.470149253731343),
        new Posicion(14.793893129770993,-18.544776119402986),
        new Posicion(-17.389312977099234,-19.58955223880597),
        new Posicion(-23.618320610687025,-0.7835820895522387),
        new Posicion(6.4885496183206115,-6.529850746268657),
        new Posicion(-6.4885496183206115,-6.529850746268657),
        new Posicion(22.580152671755727,-1.3059701492537314)
    };

    //Tendremos almacenada la posición anterior del balon.
    Posicion posicionAnteriorBalon = new Posicion(0.0, 0.0);


    class TacticaDetalleImpl implements TacticaDetalle {

        public String getNombre() {
            return "La_Isla_FC";
        }

        public String getPais() {
            return "España";
        }

        public String getEntrenador() {
            return "Er_Rixar";
        }

        public Color getColorCamiseta() {
            return new Color(204, 255, 204);
        }

        public Color getColorPantalon() {
            return new Color(102, 102, 0);
        }

        public Color getColorFranja() {
            return new Color(102, 255, 153);
        }

        public Color getColorCalcetas() {
            return new Color(0, 102, 102);
        }

        public Color getColorPortero() {
            return new Color(250, 139, 105        );
        }

        public EstiloUniforme getEstilo() {
            return EstiloUniforme.FRANJA_DIAGONAL;
        }

        public Color getColorCamiseta2() {
            return new Color(54, 122, 132);
        }

        public Color getColorPantalon2() {
            return new Color(51, 84, 123);
        }

        public Color getColorFranja2() {
            return new Color(134, 49, 182);
        }

        public Color getColorCalcetas2() {
            return new Color(155, 44, 239);
        }

        public Color getColorPortero2() {
            return new Color(129, 230, 68        );
        }

        public EstiloUniforme getEstilo2() {
            return EstiloUniforme.SIN_ESTILO;
        }

        class JugadorImpl implements JugadorDetalle {

            String nombre;
            int numero;
            Color piel, pelo;
            double velocidad, remate, presicion;
            boolean portero;
            Posicion posicion;

            public JugadorImpl(String nombre, int numero, Color piel, Color pelo,
                double velocidad, double remate, double presicion, boolean portero) {
                this.nombre=nombre;
                this.numero=numero;
                this.piel=piel;
                this.pelo=pelo;
                this.velocidad=velocidad;
                this.remate=remate;
                this.presicion=presicion;
                this.portero=portero;
            }

            public String getNombre() {
                return nombre;
            }

            public Color getColorPiel() {
                return piel;
            }

            public Color getColorPelo() {
                return pelo;
            }

            public int getNumero() {
                return numero;
            }

            public boolean esPortero() {
                return portero;
            }

            public double getVelocidad() {
                return velocidad;
            }

            public double getRemate() {
                return remate;
            }

            public double getPresicion() {
                return presicion;
            }

        }

        public JugadorDetalle[] getJugadores() {
            return new JugadorDetalle[]{
                new JugadorImpl("Benji Price", 1, new Color(255,200,150), new Color(50,0,0),1.0d,0.5d,1.0d, true),
                new JugadorImpl("Bruce Harper", 2, new Color(255,200,150), new Color(50,0,0),1.0d,0.5d,0.5d, false),
                new JugadorImpl("Julian Ross", 3, new Color(255,200,150), new Color(50,0,0),1.0d,0.5d,0.5d, false),
                new JugadorImpl("Clifford Yuma", 4, new Color(255,200,150), new Color(50,0,0),1.0d,0.5d,0.5d, false),
                new JugadorImpl("Ralf Peterson", 5, new Color(255,200,150), new Color(50,0,0),1.0d,0.5d,0.5d, false),
                new JugadorImpl("Terry Denton", 6, new Color(255,200,150), new Color(50,0,0),1.0d,0.5d,1.0d, false),
                new JugadorImpl("Tom Baker", 7, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,1.0d, false),
                new JugadorImpl("Óliver Atom", 8, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,1.0d, false),
                new JugadorImpl("Philip Callahan", 9, new Color(255,200,150), new Color(50,0,0),0.5d,1.0d,1.0d, false),
                new JugadorImpl("Patrick Everett", 10, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,1.0d, false),
                new JugadorImpl("Mark Lenders", 11, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,1.0d, false)
            };
        }
    }

    TacticaDetalle detalle=new TacticaDetalleImpl();
    public TacticaDetalle getDetalle() {
        return detalle;
    }

    public Posicion[] getPosicionSaca(SituacionPartido sp) {
        return alineacion3;
    }

    public Posicion[] getPosicionRecive(SituacionPartido sp) {
        return alineacion4;
    }
    
    //Nos devolverá si la pelota se encuentra dentro de nuestro área.
    public boolean dentroArea(SituacionPartido sp){
        if ((sp.balon().getX() > -27 && sp.balon().getX() < 27) && ((sp.balon().getY() < -35 && sp.balon().getY() > -52) || (sp.balon().getY() > 35 && sp.balon().getY() < 52))){
            //La pelota se encuentra dentro del área.
            return true;
        } else {
            //La pelota se encuentra fuera del área.
            return false;
        }
    }

    //Le pasaremos una posicion y nos devolvera si nos encontramos al borde del area.
    public boolean bordeArea(Posicion posJugador){
        if (posJugador.getX() < -7 || posJugador.getX() > 7){
            //La pelota se encuentra dentro del área.
            return true;
        } else {
            //La pelota se encuentra fuera del área.
            return false;
        }
    }

    //Le pasaremos una posicion y nos devolvera si nos encontramos al borde del campo.
    public boolean bordeCampo(Posicion posJugador){
        if (posJugador.getY() > -15 && posJugador.getY() < 15){
            //La pelota se encuentra en el borde del campo.
            return true;
        } else {
            //La pelota no se encuentra en el borde del campo.
            return false;
        }
    }

    //Dicha funcion recibe un indice de jugador y devuelve la posicion de un compañero para pasar.
    public Posicion companieroOptimo(SituacionPartido sp, int indiceJugador){
        //Obtenemos la posición del jugador.
        Posicion posicionJugador = sp.misJugadores()[indiceJugador];

        //Obtenemos los índices de los jugadores más cercanos al compañero.
        int[] companierosCercanos = posicionJugador.indicesMasCercanos(sp.misJugadores());

        //Definimos variables donde guardaremos los jugadores más adelantados.
        int indiceJugadorProximo = 0;

        //Dependiendo de si es el portero u otro jugador tendremos distintas distancias
        double distanciaPase;
        
        if (indiceJugador == 0)
            distanciaPase = 50;
        else
            distanciaPase = 15;

        //Recorremos el vector de jugadores.
        for (int i = 0; i < companierosCercanos.length; i++) {
            //Vamos viendo la distancia que hay de un jugador a otro.
            if (sp.balon().distancia(sp.misJugadores()[companierosCercanos[i]]) > distanciaPase){
                indiceJugadorProximo = companierosCercanos[i];
                break;
            }
        }

        //Obtenemos las posiciones del defensa más cercano.
        Posicion posicionCompaniero = sp.misJugadores()[indiceJugadorProximo];

        return posicionCompaniero;
    }


    //Nos devolverá si la pelota se encuentra dentro de nuestro campo.
    public boolean dentroMiCampo(SituacionPartido sp){
        //Obtenemos en primer lugar la posición del portero para tener una referencia.
        Posicion[] posicionesJugadores = sp.misJugadores();
        double posicionPortero = posicionesJugadores[0].getY();
        
        if (posicionPortero > 0){ //Visitante
            if (sp.balon().getY() > 0)
                return true;
        } else { //Local
            if (sp.balon().getY() < 0)
                return true;
        }
        
        return false;
    }
    
    //Nos pondrá al defensa en posición de marcaje.
    public int marcarJugador(SituacionPartido sp, int indiceDefensa){
        //Obtenemos las posiciones de mis jugadores.
        return sp.misJugadores()[indiceDefensa].indiceMasCercano(sp.rivales());
    }
    
    //Nos devolverá si un jugador se encuentra con espacios para caracolear.
    public boolean estaSolo(SituacionPartido sp, int indiceJugador){
        if (zonaIzquierdaLibre(sp, indiceJugador) || zonaSuperiorLibre(sp, indiceJugador) || zonaDerechaLibre(sp, indiceJugador))
            return true;

        return false;
    }
  
    //Dicho método nos dirá si en 49 metros cuadrados superiores existen contrarios.
    public boolean zonaSuperiorLibre(SituacionPartido sp, int indiceJugador){
        //Obtenemos la posición del jugador.
        Posicion posicionJugador = sp.misJugadores()[indiceJugador];

        //Solicitamos los límites de la zona para calcular si delante existe un jugador.
        double limiteIzquierdo = posicionJugador.getX() - 5;
        double limiteDerecho = posicionJugador.getX() + 5;
        double limiteInferior = posicionJugador.getY();
        double limiteSuperior = posicionJugador.getY() + 5;

        //Si el jugador está pegado a la línea de fondo intenta un desplazamiento lateral.
        if (posicionJugador.getY() > 47)
            return false;

        //Obtenemos los jugadores más cercanos al delantero.
        int[] rivalesCercanos = posicionJugador.indicesMasCercanos(sp.rivales());

        //Recorremos el vector de jugadores.
        for (int i = 0; i < rivalesCercanos.length; i++) {
            //Si el contrario está más adelantado que mi jugador lo tomamos como bueno
            if (sp.rivales()[rivalesCercanos[i]].getX() > limiteIzquierdo && sp.rivales()[rivalesCercanos[i]].getX() < limiteDerecho && sp.rivales()[rivalesCercanos[i]].getY() < limiteSuperior && sp.rivales()[rivalesCercanos[i]].getY() > limiteInferior)
                return false;
        }

        return true;
    }

    //Dicho método nos dirá si en 25 metros cuadrados izquierdos existen contrarios.
    public boolean zonaIzquierdaLibre(SituacionPartido sp, int indiceJugador){
        //Obtenemos la posición del jugador.
        Posicion posicionJugador = sp.misJugadores()[indiceJugador];

        //Solicitamos los límites de la zona para calcular si delante existe un jugador.
        double limiteIzquierdo = posicionJugador.getX() - 5;
        double limiteDerecho = posicionJugador.getX();
        double limiteInferior = posicionJugador.getY() - 5;
        double limiteSuperior = posicionJugador.getY() + 5;

        //Si el jugador está pegado a la línea de banda izquierda no podemos avanzar para la izquierda.
        if (posicionJugador.getX() > 29)
            return false;

        //Obtenemos los jugadores más cercanos al delantero.
        int[] rivalesCercanos = posicionJugador.indicesMasCercanos(sp.rivales());

        //Recorremos el vector de jugadores.
        for (int i = 0; i < rivalesCercanos.length; i++) {
            //Si el contrario está más adelantado que mi jugador lo tomamos como bueno
            if (sp.rivales()[rivalesCercanos[i]].getX() > limiteIzquierdo && sp.rivales()[rivalesCercanos[i]].getX() < limiteDerecho && sp.rivales()[rivalesCercanos[i]].getY() < limiteSuperior && sp.rivales()[rivalesCercanos[i]].getY() > limiteInferior)
                return false;
        }

        return true;
    }

    //Dicho método nos dirá si en 25 metros cuadrados a la derecha existen contrarios.
    public boolean zonaDerechaLibre(SituacionPartido sp, int indiceJugador){
        //Obtenemos la posición del jugador.
        Posicion posicionJugador = sp.misJugadores()[indiceJugador];

        //Solicitamos los límites de la zona para calcular si delante existe un jugador.
        double limiteIzquierdo = posicionJugador.getX();
        double limiteDerecho = posicionJugador.getX() + 5;
        double limiteInferior = posicionJugador.getY() - 5;
        double limiteSuperior = posicionJugador.getY() + 5;

        //Si el jugador está pegado a la línea de banda derecha no podemos avanzar para la derecha.
        if (posicionJugador.getX() < -29)
            return false;

        //Obtenemos los jugadores más cercanos al delantero.
        int[] rivalesCercanos = posicionJugador.indicesMasCercanos(sp.rivales());

        //Recorremos el vector de jugadores.
        for (int i = 0; i < rivalesCercanos.length; i++) {
            //Si el contrario está más adelantado que mi jugador lo tomamos como bueno
            if (sp.rivales()[rivalesCercanos[i]].getX() > limiteIzquierdo && sp.rivales()[rivalesCercanos[i]].getX() < limiteDerecho && sp.rivales()[rivalesCercanos[i]].getY() < limiteSuperior && sp.rivales()[rivalesCercanos[i]].getY() > limiteInferior)
                return false;
        }

        return true;
    }

    //Este método indicará hacia donde debería de moverse el jugador.
    public Posicion posicionOptima(SituacionPartido sp, int indiceJugador){
        //Observamos en primer lugar hacia donde podría dirigirme con la pelota.
        boolean ladoSuperior = zonaSuperiorLibre(sp, indiceJugador);
        boolean ladoIzquierdo = zonaIzquierdaLibre(sp, indiceJugador);
        boolean ladoDerecho = zonaDerechaLibre(sp, indiceJugador);

        if (ladoSuperior){
            //Obtenemos la posición del delantero.
            Posicion posicionDelantero = sp.misJugadores()[indiceJugador];

            //Obtenemos los índices de los jugadores más cercanos al delantero.
            int[] rivalesCercanos = posicionDelantero.indicesMasCercanos(sp.rivales());

            //Definimos variables donde guardaremos los jugadores más adelantados.
            int indiceJugadorProximo = 0;

            //Recorremos el vector de jugadores.
            for (int i = 0; i < rivalesCercanos.length; i++) {
                //Si el contrario está más adelantado que mi jugador lo tomamos como bueno
                if (posicionDelantero.getY() < sp.rivales()[rivalesCercanos[i]].getY()){
                    indiceJugadorProximo = rivalesCercanos[i];
                    break;
                }
            }

            //Obtenemos las posiciones del defensa más cercano.
            Posicion posicionDefensa = sp.rivales()[indiceJugadorProximo];

            //Calculamos si el jugador tiene un pasillo.
            double difPasillo = posicionDefensa.getX() - posicionDelantero.getX();
        
            //Calculamos el valor absoluto.
            if (difPasillo < 0)
                difPasillo *= -1;
        
            //Si la posición del rival está lejos continuamos recto.
            if (difPasillo > 6 || (posicionDelantero.distancia(posicionDefensa) > 15) || (posicionDelantero.getX() > 30) || (posicionDelantero.getX() < -30)) {
                //return posicionDelantero.moverPosicion(posicionDelantero.getX(), Constantes.centroArcoSup.getY());
                return posicionDelantero.setPosicion(posicionDelantero.getX(), Constantes.centroArcoSup.getY());
            } else {
                //Simulamos el desplazamiento para ver hacia donde debería moverse.
                //1º Simulamos las posiciones.
                Posicion desLado1 = posicionDelantero.setPosicion(posicionDelantero.getX()+15, Constantes.centroArcoSup.getY()); //Lado +
                Posicion desLado2 = posicionDelantero.setPosicion(posicionDelantero.getX()-15, Constantes.centroArcoSup.getY()); //Lado -
        
                //2º Comprobamos las distancias con respecto al delantero.
                double difLado1 = posicionDefensa.distancia(desLado1);
                double difLado2 = posicionDefensa.distancia(desLado2);
        
                //3º Nos dirigimos a la posición más lejana con respecto al delantero.
                if (difLado1 > difLado2){
                    return posicionDelantero.setPosicion(posicionDelantero.getX()+50, Constantes.centroArcoSup.getY());
                } else {
                    return posicionDelantero.setPosicion(posicionDelantero.getX()-50, Constantes.centroArcoSup.getY());
                }
            }
        } else if (ladoIzquierdo){
            return sp.misJugadores()[indiceJugador].setPosicion(sp.misJugadores()[indiceJugador].getX() - 15, sp.misJugadores()[indiceJugador].getY() + 5);
        } else if (ladoDerecho){
            return sp.misJugadores()[indiceJugador].setPosicion(sp.misJugadores()[indiceJugador].getX() + 15, sp.misJugadores()[indiceJugador].getY() + 5);
        }

        return sp.misJugadores()[indiceJugador].setPosicion(sp.misJugadores()[indiceJugador].getX(), sp.misJugadores()[indiceJugador].getY() + 15);
    }
    
    //Función que nos determina que hace el portero cuando tiene el balón en su poder.
    public Posicion posicionOptimaPortero(SituacionPartido sp, int indiceJugador){
        //Obtenemos la posición del portero.
        Posicion posicionPortero = sp.misJugadores()[indiceJugador];
        
        //Sacamos el índice del jugador más proximo al portero y su posición.
        int indiceJugadorProximo = posicionPortero.indiceMasCercano(sp.rivales());
        Posicion posicionDelantero = sp.rivales()[indiceJugadorProximo];
        
        //Simulamos el desplazamiento para ver hacia donde debería moverse.
        //1º Simulamos las posiciones.
        Posicion desLado1 = posicionPortero.moverPosicion(posicionPortero.getX()+15, Constantes.centroArcoSup.getY()); //Lado +
        Posicion desLado2 = posicionPortero.moverPosicion(posicionPortero.getX()-15, Constantes.centroArcoSup.getY()); //Lado -
        
        //2º Comprobamos las distancias con respecto al delantero.
        double difLado1 = posicionDelantero.distancia(desLado1);
        double difLado2 = posicionDelantero.distancia(desLado2);
        
        //3º Nos dirigimos a la posición más lejana con respecto al delantero.
        if (difLado1 > difLado2){
            return posicionPortero.moverPosicion(posicionPortero.getX()+200, Constantes.centroArcoSup.getY());
        } else {
            return posicionPortero.moverPosicion(posicionPortero.getX()-200, Constantes.centroArcoSup.getY());
        }
    }


    public Posicion posicionOptimaPorteroSinBalon(SituacionPartido sp){
        //Tomamos la posición del balón.
        Posicion posicionBalon = sp.balon();
                
        double bisectrizIzquierda = Constantes.posteIzqArcoInf.angulo(posicionBalon) / 2;
        double bisectrizDerecha = (Math.PI - Constantes.posteDerArcoInf.angulo(posicionBalon)) / 2;
        
        Posicion prolongacionIzquierda = Constantes.posteIzqArcoInf.moverAngulo(bisectrizIzquierda, 20);
        Posicion prolongacionDerecha = Constantes.posteDerArcoInf.moverAngulo((Math.PI - bisectrizDerecha), 20);

        return Posicion.Interseccion(Constantes.posteIzqArcoInf, prolongacionIzquierda, Constantes.posteDerArcoInf, prolongacionDerecha);
    }
    
    
    //Nos devolverá si el jugador está cercano al corner.
    public boolean estaEnCorner(SituacionPartido sp, int indiceJugador){
        if (sp.misJugadores()[indiceJugador].distancia(Constantes.cornerSupDer) < 7 || sp.misJugadores()[indiceJugador].distancia(Constantes.cornerSupIzq) < 7)
            return true;
        
        return false;
    }
    

    Random rand = new Random();
    LinkedList<Comando> comandos = new LinkedList<Comando>();
    
    public List<Comando> ejecutar(SituacionPartido sp) {
        //vacia la lista de comandos
        comandos.clear();

        //Lo primero que haremos será colocar a los jugadores según la estrategia.
        if (sp.golesPropios() < sp.golesRival()) { //si voy perdiendo o empatando
            //cada jugador ubicarse segun alineacion1
            for (int i = 0; i < 11; i++) {
                comandos.add(new ComandoIrA(i, alineacion2[i]));
            }
        } else {//sino, osea que voy ganando
            //cada jugador ubicarse segun alineacion2
            for (int i = 0; i < 11; i++) {
                comandos.add(new ComandoIrA(i, alineacion1[i]));
            }
        }

        //Posteriormente colocamos al portero en posición óptima.
        Posicion posicionPortero = posicionOptimaPorteroSinBalon(sp);
        comandos.add(new ComandoIrA(0, posicionPortero));

        //Si la pelota va por alto el portero se irá a la línea.
        if (dentroArea(sp) && sp.alturaBalon() > 0.5 && !sp.saco() && !sp.sacaRival()){
            //Sacamos el punto de intersección.
            Posicion puntoLineaGol = Posicion.Interseccion(posicionAnteriorBalon, sp.balon(), Constantes.posteIzqArcoInf, Constantes.posteDerArcoInf);

            if (puntoLineaGol.distancia(Constantes.centroArcoInf) < 5)
                comandos.add(new ComandoIrA(0, puntoLineaGol));
        }

        //Buscamos los jugadores más cercanos al balón y seguimos 3 la pelota.
        int[] jugadoresSeguidores = sp.balon().indicesMasCercanos(sp.misJugadores());
        
        for(int i = 0; i < 3; i++) {
            //Si uno de los jugadores es el portero y está fuera del área no irá por la pelota.
            if (jugadoresSeguidores[i] == 0 && dentroArea(sp) && (sp.balon().distancia(sp.misJugadores()[0]) < 4)){
                comandos.add(new ComandoIrA(jugadoresSeguidores[i], sp.balon()));
            }
                      
            if (jugadoresSeguidores[i] != 0){
                if ((jugadoresSeguidores[i] > 0 || jugadoresSeguidores[i] < 5) && dentroMiCampo(sp)){
                    comandos.add(new ComandoIrA(jugadoresSeguidores[i], sp.balon()));
                }
                
                if (jugadoresSeguidores[i] > 4){
                   comandos.add(new ComandoIrA(jugadoresSeguidores[i], sp.balon()));
                }
            }
        }
        
        //Programamos la acción si llevamos el balón.
        int rematan[] = sp.puedenRematar(); //Devuelve el jugador con la pelota.
        
        for (int i : rematan) {
            //Obtenemos los índices de los jugadores más cercanos.
            int[] cercanos = sp.misJugadores()[i].indicesMasCercanos(sp.misJugadores());
            
            //Si el jugador está en el corner debería de caracolear y centrar.
            if (estaEnCorner(sp, i)){
                for (int k = 10; k < -1; k--){
                    //Si el jugador está lejos de la pelota quiere decir que estará en su posición.
                    if (sp.misJugadores()[i].distancia(sp.misJugadores()[k]) > 5){
                        comandos.add(new ComandoGolpearBalon(i, sp.misJugadores()[k], 1, true));                 
                        break;
                    }
                }
                
            } else if (estaSolo(sp, i) && !estaEnCorner(sp, i)){ //Cualquier Jugador Solo
                if (i == 0){
                    if (bordeArea(sp.balon())){
                        Posicion companieroCercano = companieroOptimo(sp, 0);
                        comandos.add(new ComandoGolpearBalon(i, companieroCercano, 1, true));
                    } else {
                        comandos.add(new ComandoIrA(i, posicionOptimaPortero(sp, i)));
                        comandos.add(new ComandoGolpearBalon(i));
                    }
                } else if (i > 0 && i < 5){
                    if (bordeCampo(sp.balon())){
                        Posicion companieroCercano = companieroOptimo(sp, i);
                        comandos.add(new ComandoGolpearBalon(i, companieroCercano, 1, true));
                    } else {
                        comandos.add(new ComandoIrA(i, posicionOptima(sp, i)));
                        comandos.add(new ComandoGolpearBalon(i));
                    }
                } else {
                    comandos.add(new ComandoIrA(i, posicionOptima(sp, i)));
                    comandos.add(new ComandoGolpearBalon(i));
                }
            } else if (i == 0){ //Si el portero no está solo debería pegar un pelotazo.
                Posicion companieroCercano = companieroOptimo(sp, 0);
                comandos.add(new ComandoGolpearBalon(i, companieroCercano, 1, true));
            } else {
                //encontro un pase en falso
                boolean pase = false;
                boolean alto;
                //recorre los jugadores desde el mas lejano al mas cercano
                for (int j = 1; !pase && j < cercanos.length; j++) {
                    //si el jugador es distinto al jugador que remata y el jugador esta mas adelantado
                    if (sp.misJugadores()[i].getY() < sp.misJugadores()[cercanos[j]].getY()) {
                        //dar pase al jugador mas cercano que este en posicion mas ofensiva
                        if (sp.misJugadores()[i].distancia(sp.misJugadores()[cercanos[j]]) > 20) {
                            alto = true;
                        } else {
                            alto = false;
                        }
                        comandos.add(new ComandoGolpearBalon(i, sp.misJugadores()[cercanos[j]], .5 + rand.nextDouble() * .5, alto));
                        //encontro un pase por lo menos
                        pase = true;
                    }
                }
                //si no encontro ningun pase
                if (!pase) {
                    //da pase hacia el jugador mas cercano
                    if (sp.misJugadores()[i].distancia(sp.misJugadores()[cercanos[1]]) > 20) {
                        alto = true;
                    } else {
                        alto = false;
                    }
                    comandos.add(new ComandoGolpearBalon(i, sp.misJugadores()[cercanos[1]], .5 + rand.nextDouble() * .5, alto));
                }
            }
            
            //si el jugador que remata esta a menos de 30 metros del arco rival -> remata al arco
            if (sp.misJugadores()[i].distancia(Constantes.centroArcoSup) < 25) {
                comandos.add(new ComandoGolpearBalon(i, Constantes.centroArcoSup, 1, 18));
            } else if (sp.misJugadores()[i].distancia(Constantes.centroArcoSup) < 30){
                comandos.add(new ComandoGolpearBalon(i, Constantes.centroArcoSup, 1, true));
            }

            //Almacenaremos la posición anterior del balon para calcular las direcciones.
            if (posicionAnteriorBalon.getX() != sp.balon().getX() && posicionAnteriorBalon.getY() != sp.balon().getY())
                posicionAnteriorBalon = sp.balon();
        }
        
        return comandos;
    }
}
